<!-- 会员卡支付 -->
<template>
  <view class="pay-box">
    <slot name="title">
      <view class="title">验证身份支付</view>
      <view class="sub-title">刷卡支付自动结算会员优惠</view>
    </slot>
    <view class="cash-pay">
      <view v-if="cardInfo.useMember" class="flex flex-col items-center justify-center">
        <view
          class="flex flex-row items-center justify-center"
          style="
            margin: 20rpx 0px;
            background-color: #eee;
            width: 100rpx;
            height: 100rpx;
            border-radius: 50%;
            overflow: hidden;
          "
        >
          <view v-if="!payBean.errTxt">
            <u-icon @click="init" name="checkbox-mark" size="80rpx" color="#30dd81"></u-icon>
          </view>
          <u-icon v-else @click="init" name="info-circle-fill" size="100rpx" color="#fb7171"></u-icon>
        </view>
        <text class="info-tip">会员 {{ cardInfo.member?.customerName }} 已登陆</text>
        <u-button color="var(--kui-color-theme)" @click="placeAnOrderLogic">确认支付</u-button>
      </view>

      <view
        v-else
        style="
          margin: 20rpx 0px;
          background-color: #eee;
          width: 100rpx;
          height: 100rpx;
          border-radius: 50%;
          overflow: hidden;
        "
      >
        <u-image
          v-if="!payBean.errTxt"
          src="/static/images/other/card-read.png"
          mode="aspectFill"
          width="100rpx"
          height="100rpx"
        ></u-image>
        <u-icon v-else @click="init" name="info-circle-fill" size="100rpx" color="#fb7171"></u-icon>
      </view>

      <text class="info-tip">{{ payBean.infoTxt }}</text>
      <text class="err-tip" @click="init">{{ payBean.errTxt }}</text>
    </view>
    <!-- 正在支付遮罩层 -->
    <payMask ref="refPayMask" />

    <!-- 弹窗提示 - 主要用于显示一些错误信息 -->
    <resultPopup ref="refCommonPopup"> </resultPopup>
  </view>
</template>
<script setup>
import { computed, onBeforeUnmount, onMounted, reactive, ref } from "vue";
import { asyncExecFunction } from "@/king-components/js/KingonPlus";
import payMask from "./pay-mask.vue";
import { getCardByCustomerId, getCustomerInfoByCard, payBuffetOrder } from "@/api";
import { useStore } from "vuex";
import resultPopup from "@/components/common-popup/result-popup.vue";
import { calcPayType, placeAnOrder } from "./payUtils";
import { getDeviceConfig } from "@/common/devices-config";

const refCommonPopup = ref();
const store = useStore();

const props = defineProps({
  // 应收款金额
  modelMoney: {
    type: [String, Number],
    default: "0",
  },
  // 选择的餐补信息
  mealSupplementPushToNext: {
    type: Array,
    default() {
      return [];
    },
  },
  hookPlaceAnOrder: {
    type: Function,
    // 不使用时请不要传递该参数 ，必须是 async 函数
  },
});

const useMealSupplements = computed(() => props.mealSupplementPushToNext);

const payBean = reactive({
  // 支付方式(此处指该组件的固定类型名称，用于区分收款结束时的展示状态)
  payType: "card",
  // 支付验证(此处指刷卡0/人脸1)方式 （目前只有会员支付有次判定）
  // way: 0,
  // 支付状态  'reading' 'paying', 'success', 'fail', 'cancel'
  status: "reading",
  // 应收金额
  money: props.modelMoney,
  // 支付金额 （除了现金支付外，其他支付 支付金额 = 应收金额）
  amount: props.modelMoney,
  // 显示消息
  infoTxt: "", // "请将头部保持在摄像区域",
  // 错误消息
  errTxt: "", //"检测失败 / 会员卡识别失败",
  // 下单成功后的订单号
  orderId: "",
  //--- 特殊参数 -----------------------------------------------------------------------------------
  // 支付的会员信息（如果已登录会员则返回登录的会员信息，并用于支付，否则将返回NFC识别到的会员信息）
  payMerber: null,
});

// 会员卡信息
const cardInfo = reactive({
  CardCode: "",
  tip: "",
  useMember: false,
  // 会员信息
  member: {},
  // 会员卡信息
  card: {},
});

// 人脸信息
const faceInfo = ref({});

// 支付结束
const payFinsh = async (result) => {
  statusTips.Member.success();
  refPayMask.value.close();
  uni.$emit("pay:finish", { type: payBean.status, money: payBean.amount, payBean: payBean, result });
  emits("pay-finish", { type: payBean.status, money: payBean.amount, payBean: payBean, result });
};

const emits = defineEmits(["pay-finish"]);

const init = async () => {
  // 查询用户是否登陆了会员（在购物车页面）
  const { useMember, member } = store.getters.currShoppingCardInfo;
  // 如果已经有了会员信息，则直接不进行读卡，直接显示二次确认按钮
  if (useMember && member) {
    cardInfo.member = member;
    cardInfo.useMember = useMember;
    payBean.payMerber = member;
    return;
  }

  try {
    statusTips.Member.reading();
    const result = await await asyncExecFunction("HnXfjPortInit", getDeviceConfig("nfc").params);
    const data = JSON.parse(result);
    if (data.Action == "OnCardreaded") {
      cardInfo.CardCode = data.CardNumb;
      statusTips.Member.placing();
      // 执行查询，下单逻辑
      // ------------------------
      placeAnOrderLogic();
    }
  } catch (e) {
    console.error("HnXfjPortInit", e);
    statusTips.Member.fail(e);
  }
};

// 提取会员信息查询逻辑
const queryMemberInfo = async () => {
  if (!cardInfo.useMember) {
    const { data: memberInfo } = await getCustomerInfoByCard({ physicalCardNumber: cardInfo.CardCode });
    if (!memberInfo) throw new Error("会员信息不存在");
    cardInfo.member = memberInfo;
    payBean.payMerber = memberInfo;
  }

  const { data: card } = await getCardByCustomerId({ customerId: cardInfo.member?.customerInformationId });
  if (!card) throw new Error("卡信息不存在");
  cardInfo.card = card;
};

// 提取自定义下单逻辑
const handleCustomPlaceOrder = async () => {
  const { data, success: isplaced, msg, skipPay } = await props.hookPlaceAnOrder(cardInfo);
  if (!isplaced) throw new Error(msg || "下单失败");
  payBean.orderId = data.parentId;
  return { orderId: data.parentId, skipPay };
};

// 提取默认下单逻辑
const handleDefaultPlaceOrder = async () => {
  const {
    data,
    success: isplaced,
    msg,
  } = await placeAnOrder({
    memberInfo: cardInfo.member || {},
    payType: calcPayType(cardInfo.card, payBean.payType),
    specialParam: {
      mealSupplement: useMealSupplements.value.map((v) => v.name).join(",") || "",
      mealSupplementId: useMealSupplements.value.map((v) => v.materialRecipeLevelId).join(",") || "",
      isUse: useMealSupplements.value.length > 0 ? 1 : 2,
    },
  });

  if (!isplaced) throw new Error(msg || "下单失败");
  payBean.orderId = data.parentId;
  return { orderId: data.parentId };
};

const placeAnOrderLogic = async () => {
  statusTips.Member.placing();
  refPayMask.value.open();
  refPayMask.value.setDate("下单中", "请稍等...");

  try {
    await queryMemberInfo();

    const result = props.hookPlaceAnOrder ? await handleCustomPlaceOrder() : await handleDefaultPlaceOrder();

    if (result.skipPay) {
      return payFinsh({});
    }

    statusTips.Member.paying();
    await payment(result.orderId);
  } catch (error) {
    refPayMask.value.close();
    const errText = typeof error.message == "string" ? error.message : error.data?.msg || "下单失败";
    statusTips.Member.fail(errText, true, true);
  }
};

onMounted(() => {
  init();
});

onBeforeUnmount(() => {
  // 取消会员卡读卡监听
  asyncExecFunction("HnXfjPortClose"); // 关闭串口
});

const statusTips = {
  Member: {
    reading: () => {
      payBean.infoTxt = "正在读取会员卡...";
      payBean.errTxt = "";
      payBean.status = "reading";
    },
    placing: () => {
      payBean.infoTxt = "正在下单";
      payBean.errTxt = "";
      payBean.status = "placing";
    },
    paying: () => {
      payBean.infoTxt = "正在支付";
      payBean.errTxt = "";
      payBean.status = "paying";
    },
    success: (text) => {
      payBean.infoTxt = text || "支付成功";
      payBean.errTxt = "";
      payBean.status = "success";
    },
    fail: (errTxt, openPopup = false, reInitNfc = false) => {
      payBean.infoTxt = "";
      payBean.errTxt = errTxt || "会员卡识别失败";
      payBean.status = "fail";
      if (openPopup) {
        // 弹出错误提示框
        refCommonPopup.value.open({
          title: "失败",
          content: errTxt,
          type: "fail",
          //----
          // 自定义数据
          onConfirm: () => {
            if (reInitNfc) init();
          },
        });
      }
    },
  },
};

const refPayMask = ref();

/** 支付逻辑 */
const payment = async (parentId) => {
  // 会员信息
  refPayMask.value.setDate("支付中", "请等待支付结果");
  try {
    const pam = {
      // knCustomerInformationId: customerInformationId,
      payType: calcPayType(cardInfo.card, payBean.payType), // 支付方式（1余额2微信3支付宝4现金5套餐6刷卡(注意不是会员卡)7货到付款）
      parentId: parentId,
    };
    const { data, success } = await payBuffetOrder(pam);
    if (!success) throw new Error("支付失败");
    // @payStatus  NO_PAY-待支付, FAIL-失败, SUCCESS-成功, CLOSE-支付关闭
    if (data.payStatus != "SUCCESS") throw new Error(data.remark || "支付失败");
    refPayMask.value.close();
    statusTips.Member.success("支付成功");
    payFinsh(data);
  } catch (error) {
    if (error?.data?.msg == "订单已经支付请刷新") {
      statusTips.Member.success("订单已支付");
      return payFinsh({});
    }
    statusTips.Member.fail(error.message || "支付失败", true, false);
  }
  // 重新抛出异常
  throw error;
};

/** 循环购物车列表整合备注信息 */
const getRemark = () => {
  if (!Array.isArray(list) || list.length == 0) return "";
  return store.getters.shoppingCart
    .map((v) => {
      return `${v.name}: ${v.remark};`;
    })
    .join("\n");
};
</script>
<style lang="scss" scoped>
.pay-box {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 10rpx;
  width: 100%;
  box-sizing: border-box;

  .title {
    margin-top: 20rpx;
    font-weight: bold;
  }

  .sub-title {
    margin-top: 10rpx;
    font-size: 10rpx;
    color: lightgray;
  }

  .cash-pay {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;

    .err-tip {
      color: red;
      font-size: 8rpx;
      display: block;
      padding: 5rpx 0;
      max-width: 80%;
      text-align: center;
    }

    .info-tip {
      color: lightgray;
      font-size: 8rpx;
      display: block;
      padding: 5rpx 0;
    }
  }
}
</style>
